#include "ip.h"
#include "icmp.h"
#include "arpcache.h"
#include "rtable.h"
#include "arp.h"

// #include "log.h"

#include <stdio.h>
#include <stdlib.h>

// initialize ip header 
void ip_init_hdr(struct iphdr *ip, u32 saddr, u32 daddr, u16 len, u8 proto)
{
	ip->version = 4;
	ip->ihl = 5;
	ip->tos = 0;
	ip->tot_len = htons(len);
	ip->id = rand();
	ip->frag_off = htons(IP_DF);
	ip->ttl = DEFAULT_TTL;
	ip->protocol = proto;
	ip->saddr = htonl(saddr);
	ip->daddr = htonl(daddr);
	ip->checksum = ip_checksum(ip);
}

// lookup in the routing table, to find the entry with the same and longest prefix.
// the input address is in host byte order
rt_entry_t *longest_prefix_match(u32 dst)
{
	//fprintf(stdout,"longest\n");
	//fprintf(stdout, "dest:"IP_FMT"\n", HOST_IP_FMT_STR(dst));
	rt_entry_t *rt_p;
	rt_entry_t *max_rt = NULL;
	u32 long_mask = NULL;
	list_for_each_entry(rt_p, &rtable, list){
		if((rt_p->mask > long_mask) && ((rt_p->dest & rt_p->mask) == (dst & rt_p->mask))){
			long_mask = rt_p->mask;
			max_rt = rt_p;
		}
	}
	//fprintf(stdout, "dest:"IP_FMT"\n",HOST_IP_FMT_STR(dst));
	//fprintf(stdout, "max rt.dest:"IP_FMT"\t max rt.gw "IP_FMT"\n",HOST_IP_FMT_STR(max_rt->dest),HOST_IP_FMT_STR(max_rt->gw));
	return max_rt;
}

// send IP packet
//
// Different from forwarding packet, ip_send_packet sends packet generated by
// router itself. This function is used to send ICMP packets.
void ip_send_packet(char *packet, int len)
{
	struct iphdr *iph = packet_to_ip_hdr(packet);
	u32 dest_ip = ntohl(iph->daddr);
	rt_entry_t *rt = longest_prefix_match(dest_ip);
	if(rt!=NULL && rt->gw){
		iface_send_packet_by_arp(rt->iface, rt->gw, packet, len);
	}else{
		iface_send_packet_by_arp(rt->iface, dest_ip, packet, len);
	}
}
